import logging, pygame, os
log = logging.getLogger( 'XOMuncher.gamestate' )
log.setLevel( logging.DEBUG )

from olpcgames import pangofont
import olpcgames
from gettext import gettext as _ 

from monster import Monster
from player import Player
from board import Board

pygame.init()
ouch_sound = pygame.mixer.Sound("sounds/ouch.wav")

top=1
grid1=1
grid2=1
bottom=1

class GameState(dict):

    def __init__(self, width = 1, height = 1):
        self.MonsterList = Monster() # blank monster list   [append later] to get more
        self.PlayerList  = Player() #blank player list
        self.GameBoard   = Board(width, height) # blank board

        # directional enums ... as constants, can be pythonic enums later
        self.UP = 1
        self.DOWN = 2
        self.LEFT = 3
        self.RIGHT = 4

        self.cached_top = None        

        # initialize the local player's name (can be changed whe PlayerList changes)
        self.local_player = self.PlayerList[0]


    def MovePlayer(self, name, direction):
        ''' move a player in a certain direction

        if it can't be moved in that direction, it returns 0
        else return 1
        '''

        player_pos = self.PlayerList.GetPos(name) #raises error if it fails
        width = self.GameBoard.WIDTH
        height = self.GameBoard.HEIGHT

        # edge detection (index 0 is X, index 1 is Y)
        if direction == self.UP   and player_pos[1] == 0:
            return 0 # top of board
        if direction == self.DOWN and player_pos[1] == (height -1):
            return 0 # bottom of board
        if direction == self.LEFT and player_pos[0] == 0:
            return 0 # left of board
        if direction == self.RIGHT and player_pos[0] == (width -1):
            return 0 # right edge of board

        # move the player
        if direction == self.UP:
            self.PlayerList.SetY(name, player_pos[1]-1)
        elif direction == self.DOWN:
            self.PlayerList.SetY(name, player_pos[1]+1)
        elif direction == self.LEFT:
            self.PlayerList.SetX(name, player_pos[0]-1)
        elif direction == self.RIGHT:
            self.PlayerList.SetX(name, player_pos[0]+1)
        
        # return good value
        return 1
            
        




    def ToXML(self):
        """ converts the game state to XML """
        pass
    def FromXML(self):
        """ loads the game state from XML """
        pass

    # zip it up if necessary for the toXML to ZIP ?
    # can you read direct zip -> xml object?

    def getRadius(self, grid):
        radius = min(grid.get_width() / self.GameBoard.WIDTH, grid.get_height() / self.GameBoard.HEIGHT) * 0.45
        return radius

    def drawBoard(self, screen, fgcolor = (0,0,0), bgcolor = (225,225,225), flag=1):    
        """Draw the game board
           Notes: All int conversions [int()] are for shutting up python's DeprecationWarning
                  TODO: Handle multiple players/monsters at same coord
        """
        global top
        global grid1
        global grid2
        global bottom
        WIDTH = self.GameBoard.WIDTH
        HEIGHT = self.GameBoard.HEIGHT
        players = self.PlayerList
        monsters = self.MonsterList
        this_player = players[0:6] #Temporary
        
        #Start with the grid
        if flag==1 or grid1==1 or grid2==1 or top==1 or bottom==1:
            grid1 = pygame.Surface((int(screen.get_width() * 0.95), int(screen.get_height() * 0.70))) #Covers 95% of width & 70% of height- completely arbitrary
            grid1.fill(bgcolor)

            # attempt to optimize
            grid_width = grid1.get_width()
            grid_height = grid1.get_height()

            for i in range(0, WIDTH + 1): #Vertical lines
                x = (grid_width / WIDTH * i)
                pygame.draw.line(grid1, fgcolor, (x,0), (x,grid_height), 3)
            for i in range(0, HEIGHT + 1):  #Horizontal lines
                y = (grid_height / HEIGHT * i)
                pygame.draw.line(grid1, fgcolor, (0,y), (grid_width,y), 3)
            pygame.draw.rect(grid1, fgcolor, (0,0,grid_width,grid_height), 3); #To even it out a bit
        
            #Grid text
            max_len = self.GameBoard.max_text_length
            text_size = grid_width / WIDTH / max_len / 4.0
            if self.GameBoard.cached_fonts == None:
                # if the board has not been drawn before (no cached fonts)
                # or something has been changed that requires a reinit
                self.GameBoard.cached_fonts = WIDTH * HEIGHT * [None]
                font = pangofont.PangoFont(family=None, size=text_size)

                for i in range(0, HEIGHT):
                    for j in range(0, WIDTH):
                        x = (grid_width  * (j + 0.5)) / WIDTH
                        y = (grid_height * (i + 0.5)) / HEIGHT
                        if self.GameBoard[i*WIDTH+j] == None:
                            continue
                        else:
                            text_out = _(str(self.GameBoard[i*WIDTH+j]))        
                        self.GameBoard.cached_fonts[i*WIDTH+j] = font.render(text_out,True,fgcolor,bgcolor)

            for i in range(0, HEIGHT):
                for j in range(0, WIDTH):
                    x = (grid_width  * (j + 0.5)) / WIDTH
                    y = (grid_height * (i + 0.5)) / HEIGHT
                    if self.GameBoard[i*WIDTH+j] == None:
                        continue
                    fcache = self.GameBoard.cached_fonts[i*WIDTH+j]
                    grid1.blit(fcache, (x-fcache.get_width()/2,y-fcache.get_height()/2))


        if flag==2 or grid1==1 or grid2==1 or top==1 or bottom==1:
            grid2 = pygame.Surface((int(screen.get_width() * 0.95), int(screen.get_height() * 0.70))) #Covers 95% of width & 70% of height- completely arbitrary
            grid2.fill([10,10,10])
            grid2.set_colorkey([10,10,10])
            grid_width = grid1.get_width()
            grid_height = grid1.get_height()
            
            #Players
            for i in xrange(0,len(players),players.ARRAY_LENGTH):
                player = players[i:i+players.ARRAY_LENGTH]
                player_x = player[players.INDEX_X]
                player_y = player[players.INDEX_Y]
                x = (grid_width  * (player_x + 0.5)) / WIDTH
                y = (grid_height * (player_y + 0.5)) / HEIGHT
                pygame.draw.circle(grid2, player[players.INDEX_COLOR], (int(x),int(y)), int(self.getRadius(grid2)), 5) #Just a circle for now
            
            #Monsters
            for i in xrange(0,len(monsters),3):
                monster = monsters[i:i+3]
                radius = min(grid2.get_width() / WIDTH, grid2.get_height() / HEIGHT) * 0.80
                x = (2 * monster[1] * grid_width  + grid_width) / (2 * WIDTH) - radius / 2
                y = (2 * monster[2] * grid_height + grid_height) / (2 * HEIGHT) - radius / 2
                pygame.draw.rect(grid2, (225,0,0), (x,y,radius,radius), 3) #Just a red square for now
        
            #Top (problem)
            top = pygame.Surface((screen.get_width(), int(screen.get_height() * 0.15))) #Covers top 15% of screen
            top.fill(bgcolor)
            if self.cached_top == None:
                font = pangofont.PangoFont(family=None, size=screen.get_height() * 0.05) 
                prob = font.render(_(self.GameBoard.description),True,fgcolor,bgcolor)
                self.cached_top = prob
            else:
                prob = self.cached_top
            top.blit(prob, (top.get_width()/2 - prob.get_width()/2, top.get_height()/2 - prob.get_height()/2))
            
            #Bottom (score & level)
            bottom = pygame.Surface((screen.get_width(), int(screen.get_height() * 0.15))) #Covers bottom 15% of screen
            bottom.fill(bgcolor)
            font = pangofont.PangoFont(family=None, size=screen.get_height() * 0.04)     
            score = _("Score: " + str(this_player[players.INDEX_SCORE]))
            score = font.render(score,True,fgcolor,bgcolor)
            bottom.blit(score, (top.get_width() * 0.025, bottom.get_height()/2 - score.get_height()/2))
            lives = _("Lives: " + str(this_player[players.INDEX_LIVES]))
            lives = font.render(lives,True,fgcolor,bgcolor)
            bottom.blit(lives, (top.get_width() * 0.975 - lives.get_width(), bottom.get_height()/2 - lives.get_height()/2))
    
        #Now blit the surfaces to the screen
        screen.blit(top, (screen.get_width()/2 - top.get_width()/2, 0))
        grid= pygame.Surface((int(screen.get_width() * 0.95), int(screen.get_height() * 0.70))) #Covers 95% of width & 70% of height- completely arbitrary
        screen.blit(grid1, (screen.get_width() * 0.025, screen.get_height() * 0.15))
        screen.blit(grid2, (screen.get_width() * 0.025, screen.get_height() * 0.15))
        #screen.blit(grid, (screen.get_width() * 0.025, screen.get_height() * 0.15))
        screen.blit(bottom, (screen.get_width()/2 - top.get_width()/2, screen.get_height() * 0.85))    
    
    def Munch(self, player_name):
        ''' Munch for a picture's X and Y values, and increment or decrement score
            edit the board accordingly
            
            returns 1 if something happened
            returns 0 if player was on a None square
        '''
        player_pos = self.PlayerList.GetPos(player_name) #raises error if it fails
        board_value = self.GameBoard.GetValue(player_pos[0], player_pos[1]) #value at the board at the player's position

        # nothing there
        if board_value == None:
            return 0

        # check if it's in the allowed list
        if (board_value in self.GameBoard.allowed):
            # increment the score of the player
            self.PlayerList.AddScore(player_name, 1)
        else:
            # do not allow negative values for now (code in Player class)
            self.PlayerList.AddScore(player_name, -1)
            self.PlayerList.AddLives(player_name, -1) # subtract a life
            # PUT CODE HERE THAT DIES IF LIVES IS 0 and PLAY DIE SOUND
            ouch_sound.play(0)
            
        # clear the board position
        self.GameBoard.SetValue(player_pos[0], player_pos[1], self.GameBoard.VALUE_NONE)

        
